package paidaxing.blog.post.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import paidaxing.blog.common.result.PageResult;
import paidaxing.blog.post.dto.AuthorDTO;
import paidaxing.blog.post.dto.PostDTO;
import paidaxing.blog.post.dto.PostStatsDTO;
import paidaxing.blog.post.dto.request.PostQueryRequest;
import paidaxing.blog.post.dto.request.PostRequestDTO;
import paidaxing.blog.post.entity.Posts;
import paidaxing.blog.post.entity.PostTags;
import paidaxing.blog.post.mapper.PostsDao;
import paidaxing.blog.post.mapper.PostTagsDao;
import paidaxing.blog.post.service.PostsService;
import paidaxing.blog.post.utils.RequestConverter;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 文章服务实现类
 */
@Service("postsService")
public class PostsServiceImpl implements PostsService {

    @Autowired
    private PostsDao postsDao;

    @Autowired
    private PostTagsDao postTagsDao;
    
    /**
     * 通过REST API获取作者信息，避免模块间循环依赖
     * 
     * @param userId 用户ID
     * @return 作者信息
     */
    private AuthorDTO getAuthorInfo(Long userId) {
        try {
            // 注意：这里应该使用实际的用户服务地址
            // 为避免硬编码，应该从配置文件中读取
            String userServiceUrl = "http://localhost:2025/api/users/" + userId;
            
            RestTemplate restTemplate = new RestTemplate();
            String jsonResponse = restTemplate.getForObject(userServiceUrl, String.class);
            
            if (jsonResponse != null) {
                ObjectMapper mapper = new ObjectMapper();
                JsonNode rootNode = mapper.readTree(jsonResponse);
                JsonNode dataNode = rootNode.get("data");
                
                if (dataNode != null) {
                    AuthorDTO author = new AuthorDTO();
                    author.setId(dataNode.get("id").asLong());
                    author.setUsername(dataNode.get("username").asText());
                    author.setNickname(dataNode.get("nickname").asText());
                    author.setAvatar(dataNode.get("avatar").asText());
                    return author;
                }
            }
        } catch (RuntimeException e) {
            // 网络异常或解析异常
        } catch (Exception e) {
            // 其他异常
        }
        return null;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PostDTO createPost(PostRequestDTO postRequestDTO) {
        PostDTO postDTO = RequestConverter.toPostDTO(postRequestDTO);

        Date now = new Date();

        Posts posts = new Posts();
        posts.setUserId(postDTO.getUserId());
        posts.setTitle(postDTO.getTitle());
        posts.setContent(postDTO.getContent());
        posts.setExcerpt(postDTO.getExcerpt());
        posts.setCoverImage(postDTO.getCoverImage());
        posts.setStatus(postDTO.getStatus());
        posts.setIsTop(postDTO.getIsTop());
        posts.setIsRecommend(postDTO.getIsRecommend());
        posts.setPassword(postDTO.getPassword());
        posts.setUserId(postDTO.getUserId());
        posts.setCategoryId(postDTO.getCategoryId());
        posts.setCreatedAt(now);
        posts.setUpdatedAt(now);
        posts.setDeleted(0);

        //插入post表
        postsDao.insert(posts);

        List<Long> tagIds = postDTO.getTagIds();
        if (tagIds != null && !tagIds.isEmpty()) {
            List<PostTags> postTagsList = tagIds.stream().map(tagId -> {
                PostTags postTags = new PostTags();
                postTags.setPostId(posts.getId());
                postTags.setTagId(tagId);
                postTags.setCreatedAt(now);
                return postTags;
            }).collect(Collectors.toList());

            //插入postTag关联表
            postTagsDao.insertBatch(postTagsList);
        }

        postDTO.setId(posts.getId());
        postDTO.setCreatedAt(posts.getCreatedAt());
        postDTO.setUpdatedAt(posts.getUpdatedAt());
        postDTO.setDeleted(posts.getDeleted());

        return postDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PostDTO updatePost(Long id, PostRequestDTO postRequestDTO) {
        Posts existingPost = postsDao.queryById(id);
        if (existingPost == null) {
            return null;
        }

        PostDTO postDTO = RequestConverter.toPostDTO(postRequestDTO);

        existingPost.setTitle(postDTO.getTitle());
        existingPost.setContent(postDTO.getContent());
        existingPost.setExcerpt(postDTO.getExcerpt());
        existingPost.setCoverImage(postDTO.getCoverImage());
        existingPost.setStatus(postDTO.getStatus());
        existingPost.setIsTop(postDTO.getIsTop());
        existingPost.setIsRecommend(postDTO.getIsRecommend());
        existingPost.setPassword(postDTO.getPassword());
        existingPost.setUserId(postDTO.getUserId());
        existingPost.setCategoryId(postDTO.getCategoryId());
        existingPost.setUpdatedAt(new Date());

        postsDao.update(existingPost);

        postTagsDao.deleteByPostId(id);
        List<Long> tagIds = postDTO.getTagIds();
        if (tagIds != null && !tagIds.isEmpty()) {
            Date now = new Date();
            List<PostTags> postTagsList = tagIds.stream().map(tagId -> {
                PostTags postTags = new PostTags();
                postTags.setPostId(id);
                postTags.setTagId(tagId);
                postTags.setCreatedAt(now);
                return postTags;
            }).collect(Collectors.toList());

            postTagsDao.insertBatch(postTagsList);
        }

        postDTO.setId(existingPost.getId());
        postDTO.setCreatedAt(existingPost.getCreatedAt());
        postDTO.setUpdatedAt(existingPost.getUpdatedAt());
        postDTO.setDeleted(existingPost.getDeleted());

        return postDTO;
    }

    @Override
    public PostDTO getPostDetail(Long id) {
        Posts posts = postsDao.queryById(id);
        if (posts == null) {
            return null;
        }

        PostDTO postDTO = new PostDTO();
        postDTO.setId(posts.getId());
        postDTO.setTitle(posts.getTitle());
        postDTO.setContent(posts.getContent());
        postDTO.setExcerpt(posts.getExcerpt());
        postDTO.setCoverImage(posts.getCoverImage());
        postDTO.setStatus(posts.getStatus());
        postDTO.setViewCount(posts.getViewCount());
        postDTO.setLikeCount(posts.getLikeCount());
        postDTO.setCommentCount(posts.getCommentCount());
        postDTO.setIsTop(posts.getIsTop());
        postDTO.setIsRecommend(posts.getIsRecommend());
        postDTO.setPassword(posts.getPassword());
        postDTO.setUserId(posts.getUserId());
        postDTO.setCategoryId(posts.getCategoryId());
        postDTO.setPublishedAt(posts.getPublishedAt());
        postDTO.setCreatedAt(posts.getCreatedAt());
        postDTO.setUpdatedAt(posts.getUpdatedAt());
        postDTO.setDeleted(posts.getDeleted());
        
        // 获取作者信息
        try {
            // 通过REST API调用获取用户信息，避免模块间循环依赖
            AuthorDTO author = this.getAuthorInfo(posts.getUserId());
            postDTO.setAuthor(author);
        } catch (Exception e) {
            // 获取作者信息失败，记录日志但不影响文章详情返回
        }

        return postDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deletePost(Long id) {
        Posts existingPost = postsDao.queryById(id);
        if (existingPost == null) {
            return false;
        }

        postTagsDao.deleteByPostId(id);
        return postsDao.deleteById(id) > 0;
    }

    @Override
    public PageResult<PostDTO> listPosts(PostQueryRequest queryRequest) {
        Posts posts = new Posts();
        if (queryRequest.getStatus() != null && !queryRequest.getStatus().isEmpty()) {
            posts.setStatus(queryRequest.getStatus());
        }
        if (queryRequest.getCategoryId() != null) {
            posts.setCategoryId(queryRequest.getCategoryId());
        }
        if (queryRequest.getUserId() != null) {
            posts.setUserId(queryRequest.getUserId());
        }
        if (queryRequest.getIsTop() != null) {
            posts.setIsTop(queryRequest.getIsTop());
        }
        if (queryRequest.getIsRecommend() != null) {
            posts.setIsRecommend(queryRequest.getIsRecommend());
        }
        
        if (queryRequest.getOrderBy() != null && !queryRequest.getOrderBy().isEmpty()) {
            posts.setOrderBy(queryRequest.getOrderBy());
        }
        if (queryRequest.getAsc() != null) {
            posts.setAsc(queryRequest.getAsc());
        }

        if (queryRequest.getKeyword() != null && !queryRequest.getKeyword().isEmpty()) {
            posts.setTitle(queryRequest.getKeyword());
        }

        int offset = (queryRequest.getPageNo() - 1) * queryRequest.getPageSize();
        int limit = queryRequest.getPageSize();

        long total = 0;
        List<Posts> postsList;

        if (queryRequest.getTagId() != null) {
            List<Long> postIds = postTagsDao.selectPostIdsByTagIds(Collections.singletonList(queryRequest.getTagId()));
            
            if (postIds.isEmpty()) {
                postsList = Collections.emptyList();
                total = 0;
            } else {
                postsList = postsDao.selectPostsByTagAndPage(posts, postIds, offset, limit);
                total = postsDao.countByPostIds(posts, postIds);
            }
        } else {
            postsList = postsDao.selectPostsByPage(posts, offset, limit);
            total = postsDao.count(posts);
        }

        List<PostDTO> postDTOList = postsList.stream().map(post -> {
            PostDTO postDTO = new PostDTO();
            postDTO.setId(post.getId());
            postDTO.setTitle(post.getTitle());
            postDTO.setExcerpt(post.getExcerpt());
            postDTO.setCoverImage(post.getCoverImage());
            postDTO.setStatus(post.getStatus());
            postDTO.setViewCount(post.getViewCount());
            postDTO.setLikeCount(post.getLikeCount());
            postDTO.setCommentCount(post.getCommentCount());
            postDTO.setIsTop(post.getIsTop());
            postDTO.setIsRecommend(post.getIsRecommend());
            postDTO.setUserId(post.getUserId());
            postDTO.setCategoryId(post.getCategoryId());
            postDTO.setPublishedAt(post.getPublishedAt());
            postDTO.setCreatedAt(post.getCreatedAt());
            postDTO.setUpdatedAt(post.getUpdatedAt());
            
            // 获取作者信息
            try {
                // 通过REST API调用获取用户信息，避免模块间循环依赖
                AuthorDTO author = this.getAuthorInfo(post.getUserId());
                postDTO.setAuthor(author);
            } catch (Exception e) {
                // 获取作者信息失败，记录日志但不影响文章列表返回
            }
            
            return postDTO;
        }).collect(Collectors.toList());

        PageResult<PostDTO> pageResult = new PageResult<>();
        pageResult.setPageNo(queryRequest.getPageNo());
        pageResult.setPageSize(queryRequest.getPageSize());
        pageResult.setTotal((int) total);
        pageResult.setRecords(postDTOList);

        return pageResult;
    }

    @Override
    public PostStatsDTO getPostStats(Long id) {
        Posts posts = postsDao.queryById(id);
        if (posts == null) {
            return null;
        }

        PostStatsDTO postStatsDTO = new PostStatsDTO();
        postStatsDTO.setId(posts.getId());
        postStatsDTO.setTitle(posts.getTitle());
        postStatsDTO.setViewCount(posts.getViewCount());
        postStatsDTO.setLikeCount(posts.getLikeCount());
        postStatsDTO.setCommentCount(posts.getCommentCount());
        
        return postStatsDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean increaseViewCount(Long id) {
        Posts posts = postsDao.queryById(id);
        if (posts == null) {
            return false;
        }

        // 处理 viewCount 为 null 的情况
        Integer viewCount = posts.getViewCount();
        if (viewCount == null) {
            viewCount = 0;
        }
        posts.setViewCount(viewCount + 1);
        posts.setUpdatedAt(new Date());
        
        return postsDao.update(posts) > 0;
    }
    
    // 移除冗余的WithLogging方法，直接在Controller中调用基本方法
}